home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlib43 / mntlib / sleep.c < prev    next >
C/C++ Source or Header  |  1993-10-20  |  4KB  |  148 lines

  1. /* sleep -- sleep for a specified number of seconds */
  2. /* usleep -- sleep for a specified number of microSecond */
  3. /* written by Eric R. Smith and placed in the public domain */
  4. /* extensively rehacked by entropy for mint >= 0.95, still public domain */
  5.  
  6. #include <time.h>
  7. #include <mintbind.h>
  8. #include <signal.h>
  9. #include <unistd.h>
  10. #include <limits.h>
  11.  
  12. /* _clock() has a rez of CLOCKS_PER_SEC ticks/sec */
  13.  
  14. #define USEC_PER_TICK (1000000L / ((unsigned long)CLOCKS_PER_SEC))
  15. #define    USEC_TO_CLOCK_TICKS(us)    ((us) / USEC_PER_TICK )
  16.  
  17. static unsigned long _alarm __PROTO((unsigned long secs));
  18.  
  19. static unsigned long
  20. _alarm(secs)
  21.     unsigned long secs;
  22. {
  23.     unsigned long r;
  24.  
  25. #ifndef __MSHORT__
  26.     if (secs > ((unsigned long) (LONG_MAX/1000)))
  27.         secs = ((unsigned long) (LONG_MAX/1000));
  28. #endif
  29.     r = Talarm((long) secs);
  30.  
  31.     return (unsigned long) r;
  32. }
  33.  
  34. static void __CDECL alarm_catch __PROTO((long signum));
  35.  
  36. static void __CDECL
  37. alarm_catch(signum)
  38.     long signum;
  39. {
  40.     return;
  41. }
  42.  
  43. unsigned int
  44. sleep(n)
  45.     unsigned int n;
  46. {
  47.     unsigned long stop;
  48.     long old_alarm_func;
  49.     long old_sigmask;
  50.     unsigned long alarm_sec;
  51.     long remain;
  52.     extern int __mint;
  53.  
  54.     if (__mint) {
  55.         if (__mint < 95) {
  56.             while (n > 32) {
  57.                 (void)Fselect(32000, 0L, 0L, 0L);
  58.                 n -= 32;
  59.             }
  60.             if (n > 0)
  61.               (void)Fselect(1000*n, 0L, 0L, 0L);
  62.             return 0;
  63.         }
  64.         if (n == 0)
  65.             return 0;
  66.         /* Clear any existing alarm, but save its expire time.
  67.            Then block all signals and save original mask.
  68.            Install our alarm handler, and remask (since Psignal()
  69.            just unmasked SIGALRM.)
  70.         */
  71.         alarm_sec = (long) Talarm(0L);
  72.         old_sigmask = Psigblock(~0L);
  73.         old_alarm_func = Psignal(SIGALRM, (long)alarm_catch);
  74.         (void) Psigblock(~0L);
  75.         /* Figure out when we would normally wake up */
  76.         stop = _clock() + n * CLOCKS_PER_SEC;
  77.         /* But only sleep as long as the original alarm clock */
  78.         if (alarm_sec && (alarm_sec < n))
  79.             (void) _alarm(alarm_sec);
  80.         else
  81.             (void) _alarm((unsigned long) n);
  82.         /* Go to sleep with the original mask but always
  83.            allow SIGALRM or we might never wake up.
  84.         */
  85.         Psigpause(old_sigmask & ~(sigmask(SIGALRM)));
  86.         /* Cancel any time left on the alarm clock */
  87.         (void) _alarm(0L);
  88.         /* Eat any alarms that occurred before we cancelled.
  89.            The Syield ensure we enter the kernel and handle the
  90.            signal.
  91.         */
  92.         (void) Psignal(SIGALRM, (long) alarm_catch);
  93.         (void) Syield();
  94.         /* Remask again after the Psignal() */
  95.         (void) Psigblock(~0L);
  96.         remain = ((long) stop - (long) _clock()) 
  97.               / (long) CLOCKS_PER_SEC;
  98.         if (alarm_sec) {
  99.             /* Restore the original timer (or if it expired,
  100.                post the signal now)
  101.             */
  102.             alarm_sec -= ((long) n - remain);
  103.             if (alarm_sec <= 0)
  104.                 (void) Pkill(Pgetpid(), SIGALRM);
  105.             else
  106.                 (void) _alarm(alarm_sec);
  107.         }
  108.         /* Restore the original alarm handler (which also
  109.            allows it to be delivered!)  Then restore the
  110.            original signal mask (if the signal handler
  111.            does a longjmp() we might lose).
  112.         */
  113.         (void) Psignal(SIGALRM, (long) old_alarm_func);
  114.         (void) Psigsetmask(old_sigmask);
  115.         (void) Syield();
  116.         return ((remain > 0) ? (unsigned) remain : 0);
  117.     }
  118.     else {
  119.         stop = _clock() + n * CLOCKS_PER_SEC;
  120.         while (_clock() < stop)
  121.             ;
  122.     }
  123.     return 0;
  124. }
  125.  
  126. /*
  127.  * Sleep for usec microSeconds 
  128.  * the actual suspension time can be arbitrarily longer
  129.  *
  130.  */
  131. void
  132. usleep(usec)
  133.     unsigned long usec;
  134. {
  135.     unsigned long    stop;
  136.     extern int __mint;
  137.  
  138.     if (__mint) {
  139.         if (usec >= 1000)
  140.             (void)Fselect((unsigned)(usec/1000), 0L, 0L, 0L);
  141.     }
  142.     else {
  143.         stop = _clock() + USEC_TO_CLOCK_TICKS(usec);
  144.         while (_clock() < stop)
  145.             ;
  146.     }
  147. }
  148.